From 788e47034becc7806485b40dbef9774a14f8ea9d Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 21 Nov 2023 21:54:10 +0100 Subject: [PATCH] luci-mod-status: add support to show/hide index cards Add support to show/hide index cards. A card's state is saved using the browser localstorage and its state is restored on page reload/relogin. Rework the pool function to check and skip loading of hidden cards. Rework themes to address new button position. Signed-off-by: Christian Marangi [ changed tabs in CSS ] Signed-off-by: Paul Donald --- .../resources/view/status/index.js | 64 ++++++++++++++++--- .../htdocs/luci-static/bootstrap/cascade.css | 32 ++++++++++ .../htdocs/luci-static/material/cascade.css | 23 +++++++ .../luci-static/openwrt2020/cascade.css | 38 +++++++++++ .../luci-static/openwrt.org/cascade.css | 42 ++++++++++++ 5 files changed, 191 insertions(+), 8 deletions(-) diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/index.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/index.js index a232f315c0..243f66daa4 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/index.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/index.js @@ -4,12 +4,42 @@ 'require poll'; 'require fs'; 'require network'; +'require ui'; return view.extend({ - invokeIncludesLoad: function(includes) { + handleToggleSection: function(include, container, ev) { + var btn = ev.currentTarget; + + include.hide = !include.hide; + + btn.setAttribute('data-style', include.hide ? 'active' : 'inactive'); + btn.firstChild.data = include.hide ? _('Show') : _('Hide'); + btn.blur(); + + container.style.display = include.hide ? 'none' : 'block'; + + if (include.hide) { + localStorage.setItem(include.id, 'hide'); + } else { + dom.content(container, + E('p', {}, E('em', { 'class': 'spinning' }, + [ _('Collecting data...') ]) + ) + ); + + localStorage.removeItem(include.id); + } + }, + + invokeIncludesLoad: function(includes, first_load) { var tasks = [], has_load = false; for (var i = 0; i < includes.length; i++) { + if (includes[i].hide && !first_load) { + tasks.push(null); + continue; + } + if (typeof(includes[i].load) == 'function') { tasks.push(includes[i].load().catch(L.bind(function() { this.failed = true; @@ -25,13 +55,16 @@ return view.extend({ return has_load ? Promise.all(tasks) : Promise.resolve(null); }, - poll_status: function(includes, containers) { + poll_status: function(includes, containers, first_load) { return network.flushCache().then(L.bind( - this.invokeIncludesLoad, this, includes + this.invokeIncludesLoad, this, includes, first_load )).then(function(results) { for (var i = 0; i < includes.length; i++) { var content = null; + if (includes[i].hide && !first_load) + continue; + if (includes[i].failed) continue; @@ -49,7 +82,8 @@ return view.extend({ containers[i].parentNode.style.display = ''; containers[i].parentNode.classList.add('fade-in'); - dom.content(containers[i], content); + if (!includes[i].hide) + dom.content(containers[i], content); } } @@ -87,19 +121,33 @@ return view.extend({ function(m, s, c) { return (s ? ' ' : '') + c.toUpperCase() }) }); + includes[i].id = title; + includes[i].hide = localStorage.getItem(includes[i].id) == 'hide'; + var container = E('div'); - rv.appendChild(E('div', { 'class': 'cbi-section', 'style': 'display:none' }, [ - title != '' ? E('h3', title) : '', + rv.appendChild(E('div', { 'class': 'cbi-section', 'style': 'display: none' }, [ + E('div', { 'class': 'cbi-title' },[ + title != '' ? E('h3', title) : '', + E('div', [ + E('span', { + 'data-style': includes[i].hide ? 'active' : 'inactive', + 'data-indicator': 'poll-status', + 'data-clickable': 'true', + 'click': ui.createHandlerFn(this, 'handleToggleSection', + includes[i], container) + }, [ _(includes[i].hide ? 'Show' : 'Hide') ]) + ]), + ]), container ])); containers.push(container); } - return this.poll_status(includes, containers).then(function() { + return this.poll_status(includes, containers, true).then(L.bind(function() { return poll.add(L.bind(this.poll_status, this, includes, containers)) - }).then(function() { + }, this)).then(function() { return rv; }); }, diff --git a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css index 6ab19035ce..c1be937697 100644 --- a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css +++ b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css @@ -2014,6 +2014,38 @@ form.inline { display: inline; margin-bottom: 0; } font-family: monospace; } +.cbi-title { + display: flex; +} + +.cbi-title div { + margin-left: 5px; + margin-right: auto; + align-self: center; +} + +.cbi-title [data-indicator] { + padding: 3px 3px 2px; + font-size: 9.75px; + font-weight: bold; + color: var(--text-color-high); + text-transform: uppercase; + white-space: nowrap; + background-color: var(--background-color-low); + border-radius: 3px; + text-shadow: none; + margin: .125em 0 .125em .4em; +} + +.cbi-title [data-indicator][data-style="active"] { + color: var(--on-primary-color); + background-color: var(--primary-color-high); +} + +.cbi-title [data-indicator][data-clickable] { + cursor: pointer; +} + .cbi-section-table .tr:hover .td, .cbi-section-table .tr:hover .th, .cbi-section-table .tr:hover::before { diff --git a/themes/luci-theme-material/htdocs/luci-static/material/cascade.css b/themes/luci-theme-material/htdocs/luci-static/material/cascade.css index 338d7b4fb3..8e491e10c9 100644 --- a/themes/luci-theme-material/htdocs/luci-static/material/cascade.css +++ b/themes/luci-theme-material/htdocs/luci-static/material/cascade.css @@ -807,6 +807,7 @@ fieldset > fieldset, } .cbi-section > h3:first-child, +.cbi-title, .panel-title { font-size: 1.4rem; line-height: 1; @@ -819,6 +820,28 @@ fieldset > fieldset, border-bottom: thin solid #eee; } +.cbi-title { + display: flex; +} + +.cbi-title > h3:first-child { + font-size: unset; + margin: unset; + padding-bottom: unset; +} + +.cbi-title [data-indicator] { + position: relative; + top: 0.2rem; + float: left; + margin-left: 0.3rem; + cursor: pointer; +} + +.cbi-title [data-indicator][data-style="active"] { + background-color: #002B49 !important; +} + .cbi-section > h4:first-child, .cbi-section > p:first-child, [data-tab-title] > h3:first-child, diff --git a/themes/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css b/themes/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css index cd8fef6a27..ec89ba5df9 100644 --- a/themes/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css +++ b/themes/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css @@ -369,6 +369,44 @@ tr.placeholder > td { * view specific table invariants */ +.cbi-title { + display: flex; + margin: 0 0 1rem 0; +} + +.cbi-title > h3{ + margin: unset; +} + +.cbi-title div { + margin-left: 5px; + margin-right: auto; + align-self: center; +} + +.cbi-title [data-indicator] { + background: var(--secondary-bright-color); + color: var(--main-bright-color); + border: 0.5px solid var(--main-bright-color); + display: inline-block; + font-size: .85em; + line-height: calc(1.5em - 1px); + padding: 0 calc(0.5em - 0.5px); + margin: 0.125em; + border-radius: 1em; + white-space: nowrap; +} + +.cbi-title [data-indicator][data-style="active"] { + background: var(--main-bright-color); + color: var(--secondary-bright-color); + border: 0.5px solid var(--secondary-bright-color); +} + +.cbi-title [data-indicator][data-clickable] { + cursor: pointer; +} + #cbi-wireless-wifi-device .ifacebadge { flex-direction: column; justify-content: space-around; diff --git a/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css b/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css index 34896af979..224c282773 100644 --- a/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css +++ b/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css @@ -565,6 +565,48 @@ p { display: none; } +.cbi-title { + display: flex; + border-bottom: 1px solid; + padding-bottom: 4px; + margin: .25em 0 .5em 0; +} + +.cbi-title > h3 { + border-bottom: unset; + padding-bottom: unset; + margin: unset; + width: unset; +} + + +.cbi-title div { + margin-left: 5px; + margin-right: auto; + align-self: center; +} + +.cbi-title [data-indicator] { + text-transform: uppercase; + background: #90c0e0 !important; + color: #000 !important; + font-size: 11px; + padding: 0.125em 0.5em; + margin: 0.125em; + border-radius: 0.6em; +} + +.cbi-title [data-indicator][data-style="inactive"] { + border: 1px solid #90c0e0; + background: #fff !important; + color: #90c0e0 !important; + padding: calc(.125em-1px) calc(.5em-1px); +} + +.cbi-title [data-indicator][data-clickable] { + cursor: pointer; +} + .cbi-title-ref { color: #37c; } -- 2.30.2